﻿using FileToVideo.AddFunc;
using FileToVideo.Class;
using FileToVideo.Config;
using FileToVideo.Enums;
using Microsoft.VisualBasic;
using OpenCvSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Range = OpenCvSharp.Range;
using Size = OpenCvSharp.Size;

namespace FileToVideo.Helpers
{
    /// <summary>
    /// 帧数据转换工具
    /// </summary>
    public class FrameDataUtils : IDisposable
    {
        /// <summary>
        /// 版本控制
        /// <br />
        /// 当前数据工具版本,用于数据兼容性判断
        /// <br />
        /// 规则: 主版本.次版本.修订版本(如: 1.0.0)
        /// <br />
        /// 当主版本变化时,表示不兼容的重大变化
        /// </summary>
        [System.ComponentModel.Description("版本号")]
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] // 防止在智能感知中显示此属性
        public static string Version { get; } = "1.0.0";

        /// <summary>
        /// 编码方式
        /// </summary>
        public EncryptMode encryptMode = EncryptMode.AES;

        /// <summary>
        /// 数据加密方式
        /// </summary>
        public CodingMode codingMode = CodingMode.NONE;

        /// <summary>
        /// 密钥
        /// </summary>
        public string password = "";

        /// <summary>
        /// 分块大小模式
        /// </summary>
        public PartSizeMode_1080P partSize = PartSizeMode_1080P.SIZE_8;

        /// <summary>
        /// 帧宽度
        /// </summary>
        public int width = Setting.width;

        /// <summary>
        /// 帧高度
        /// </summary>
        public int height = Setting.height;

        /// <summary>
        /// 是否包含Alpha通道
        /// </summary>
        public bool isRGBA = false;

        /// <summary>
        /// 颜色生成器
        /// </summary>
        private ColorGenerator colorGenerator;

        /// <summary>
        /// 默认纯色数据帧工具
        /// </summary>
        private DefaultColorFrameUtils defaultColorFrameUtils;

        /// <summary>
        /// 输出文件位置
        /// </summary>
        public string outputPath;

        /// <summary>
        /// 帧重复次数
        /// </summary>
        public int frameRepetition;

        /// <summary>
        /// 视频写入器
        /// </summary>
        private VideoWriter _videoWriter;

        /// <summary>
        /// 加密密钥
        /// </summary>
        public string Key
        {
            get
            {
                string ret = "";
                switch (encryptMode)
                {
                    case EncryptMode.AES:
                        ret = AES.GetKey(password, codingMode);
                        break;
                    case EncryptMode.BASE64:
                        ret = Base64.GetKey(password, codingMode);
                        break;
                    default:
                        ret = "";
                        break;
                }
                return ret;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="codingMode"></param>
        /// <param name="partSize"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="encryptMode"></param>
        /// <param name="isRead">是否是读取模式</param>
        /// <param name="fps">帧率</param>
        public FrameDataUtils(
            EncryptMode encryptMode,
            CodingMode codingMode,
            string password,
            PartSizeMode_1080P partSize,
            int width,
            int height,
            string outputPath,
            bool isRead = false,
            int fps = Setting.FPS,
            int frameRepetition = Setting.frameRepetition
        )
        {
            this.encryptMode = encryptMode;
            this.codingMode = codingMode;
            this.password = password;
            this.partSize = partSize;
            this.width = width;
            this.height = height;
            this.outputPath = outputPath;
            this.frameRepetition = frameRepetition;

            // 初始化颜色生成器 (这里我原本是打算允许使用密钥的,但是我现在决定颜色密钥就使用标准base64[65色])
            //this.colorGenerator = new ColorGenerator(Key.Length);
            this.colorGenerator = new ColorGenerator(Base64._keyStr.Length);

            // 初始化纯色数据帧工具
            this.defaultColorFrameUtils = new DefaultColorFrameUtils(encryptMode, outputPath,isRead);

            // 设置视频参数
            int fourcc = VideoWriter.FourCC('m', 'p', '4', 'v'); // MP4编码器
            Size frameSize = new Size(width, height); // 帧尺寸

            // 初始化视频写入器
            if (!isRead)
            {
                _videoWriter = new VideoWriter(outputPath, fourcc, fps, frameSize, true);
            }
        }

        /// <summary>
        /// 更新设置
        /// </summary>
        /// <param name="encryptMode"></param>
        /// <param name="codingMode"></param>
        public void UpdateSetting(
            EncryptMode encryptMode = EncryptMode.NONE,
            CodingMode codingMode = CodingMode.NONE,
            PartSizeMode_1080P partSize = PartSizeMode_1080P.SIZE_1,
            string outputPath = "",
            int frameRepetition = Setting.frameRepetition
        )
        {
            this.encryptMode = encryptMode;
            this.codingMode = codingMode;
        }

        /// <summary>
        /// 检测output文件
        /// </summary>
        /// <returns></returns>
        public bool OutputPathCheck()
        {
            FileInfo output = new FileInfo(outputPath);
            if (output.Exists)
            {
                // 只支持MP4格式
                if(output.Extension == ".mp4")
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 将 Mats 写入文件
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public bool WriteMats(List<Mat> mats)
        {
            //if (OutputPathCheck() == false) return false;
            // 确保VideoWriter成功打开
            if (!_videoWriter.IsOpened())
            {
                throw new Exception("无法创建视频文件，请检查编码器支持");
            }

            // 假设你有一系列Mat帧
            for (int i = 0; i < mats.Count; i++)
            {
                Mat mat = mats[i];
                _videoWriter.Write(mat); // 写入帧
                mat.Dispose(); // 释放帧资源
            }

            // 强制GC回收，确保所有资源释放
            GC.Collect();
            return true;
        }

        /// <summary>
        /// 将 Mat 写入文件
        /// <br />
        /// 会覆盖原文件
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public bool WriteMat(Mat mat)
        {
            //if (OutputPathCheck() == false) return false;
            // 确保VideoWriter成功打开
            if (!_videoWriter.IsOpened())
            {
                throw new Exception("无法创建视频文件，请检查编码器支持");
            }

            // 写入单帧
            _videoWriter.Write(mat); // 写入帧

            // 关闭VideoWriter
            _videoWriter.Release();
            return true;
        }

        /// <summary>
        /// 将数据转换为Bitmap
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public Bitmap Convert(byte[] data)
        {
            var bitmap = new Bitmap(width, height);

            

            return bitmap;
        }

        /// <summary>
        /// 将Bitmap转换为数据
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public byte[] Convert(Bitmap bitmap)
        {
            byte[] ret = new byte[0];



            return ret;
        }

        /// <summary>
        /// 按照指定的编码方式对数据进行编码
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private byte[] encode(byte[] data)
        {
            byte[] ret = data;
            switch (encryptMode)
            {
                case EncryptMode.AES:
                    ret = AES.Encrypt(data, Key);
                    break;
                case EncryptMode.BASE64:
                    string ret_str = Base64.Encode(data, Key);
                    ret = Encoding.UTF8.GetBytes(ret_str);
                    break;
                default:
                    break;
            }
            return ret;
        }

        /// <summary>
        /// 按照指定的编码方式对数据进行解码
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private byte[] decode(byte[] data)
        {
            byte[] ret = data;
            switch (encryptMode)
            {
                case EncryptMode.AES:
                    ret = AES.Decrypt(data, Key);
                    break;
                case EncryptMode.BASE64:
                    ret = Base64.Decode(data, Key);
                    break;
                default:
                    break;
            }
            return ret;
        }

        /// <summary>
        /// 将首帧数据转为字符串
        /// </summary>
        /// <param name="frame"></param>
        /// <returns></returns>
        public string ConvertFirstFrame2String(FirstFrame frame)
        {
            var frameData = frame.ToDeepSave();
            return Base64.Encode(frameData);
        }

        /// <summary>
        /// 将字符串写入视频
        /// <br />
        /// 纯色帧
        /// </summary>
        /// <param name="text"></param>
        public void WriteStringIntoVideo(string text,out int i)
        {
            // 获取颜色列表
            var colors = this.colorGenerator.GeneratedColors;

            // 确保VideoWriter成功打开
            if (!_videoWriter.IsOpened())
            {
                throw new Exception("无法创建视频文件，请检查编码器支持");
            }

            // 创建起始纯色帧并写入视频
            var startColors = this.defaultColorFrameUtils.StartColors;
            for (i = 0; i < startColors.Count; i++)
            {
                Color color = startColors[i];
                using (Mat mat = this.defaultColorFrameUtils.pureColorFrameDetector.CreateColorFrame(
                    color,
                    width,
                    height
                ))
                {
                    for (int j = 0; j < this.defaultColorFrameUtils.frameRepetition; j++)
                    {
                        using (Mat tempMat = mat.Clone())
                        {
                            _videoWriter.Write(tempMat); // 写入帧
                        }
                    }
                }
            }

            // 开始写入每个字符对应的颜色帧
            for (i = 0; i < text.Length; i++)
            {
                char c = text[i];
                int index = Base64._keyStr.IndexOf(c);
                Color color = colors[index];

                // 生成纯色帧并写入视频
                using (Mat mat = this.defaultColorFrameUtils.pureColorFrameDetector.CreateColorFrame(
                    color,
                    width,
                    height
                ))
                {
                    for (int j = 0; j < this.defaultColorFrameUtils.frameRepetition; j++)
                    {
                        using (Mat tempMat = mat.Clone())
                        {
                            _videoWriter.Write(tempMat); // 写入帧
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 将字符串写入视频
        /// <br />
        /// 纯色帧
        /// <br />
        /// 此方法会调用 loading 窗口
        /// </summary>
        /// <param name="text"></param>
        public async Task WriteStringIntoVideo(string text)
        {
            // loading
            using (Loading loading = new Loading(
                text.Length,
                "正在写入数据"
            ))
            {
                loading.Show(); // 非模态显示，这样UI线程不会阻塞，但是我们需要在后台任务中更新进度，然后等待后台任务完成。

                // 启动后台任务
                await Task.Run(() =>
                {
                    // 在后台线程中执行视频写入操作
                    // 但是注意：OpenCV的VideoWriter和Mat操作可能不是线程安全的，所以我们需要确保它们在同一线程中使用。
                    // 但是，我们这里是在同一个后台线程中执行，所以应该没问题。

                    // 获取颜色列表
                    var colors = this.colorGenerator.GeneratedColors;

                    // 确保VideoWriter成功打开
                    if (!_videoWriter.IsOpened())
                    {
                        throw new Exception("无法创建视频文件，请检查编码器支持");
                    }

                    // 创建起始纯色帧并写入视频
                    var startColors = this.defaultColorFrameUtils.StartColors;
                    int totalFrames = startColors.Count + text.Length; // 总帧数包括起始帧和数据帧

                    // 更新起始帧的进度
                    for (int i = 0; i < startColors.Count; i++)
                    {
                        Color color = startColors[i];
                        using (Mat mat = this.defaultColorFrameUtils.pureColorFrameDetector.CreateColorFrame(color, width, height))
                        {
                            for (int j = 0; j < this.defaultColorFrameUtils.frameRepetition; j++)
                            {
                                using (Mat tempMat = mat.Clone())
                                {
                                    _videoWriter.Write(tempMat);
                                }
                            }
                        }

                        // 更新进度，通过Dispatcher在UI线程上更新
                        loading.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            loading.Update(i, startColors.Count, "正在写入起始信号帧" + ".".Repeat(i % 4));
                        }), System.Windows.Threading.DispatcherPriority.Background);
                    }

                    // 开始写入每个字符对应的颜色帧
                    for (int i = 0; i < text.Length; i++)
                    {
                        char c = text[i];
                        int index = Base64._keyStr.IndexOf(c);
                        Color color = colors[index];

                        using (Mat mat = this.defaultColorFrameUtils.pureColorFrameDetector.CreateColorFrame(color, width, height))
                        {
                            for (int j = 0; j < this.defaultColorFrameUtils.frameRepetition; j++)
                            {
                                using (Mat tempMat = mat.Clone())
                                {
                                    _videoWriter.Write(tempMat);
                                }
                            }
                        }

                        loading.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            loading.Update(i, text.Length, "正在写入数据" + ".".Repeat(i % 3));
                        }), System.Windows.Threading.DispatcherPriority.Background);
                    }
                });
            }
        }

        /// <summary>
        /// 读取起始数据
        /// </summary>
        /// <returns></returns>
        public async Task<string> ReadStartData() => await this.defaultColorFrameUtils.ReadStartData();

        /// <summary>
        /// 读取色块帧数据
        /// <br />
        /// 会调用 Loading 的版本
        /// <br />
        /// 会创建 临时文件
        /// </summary>
        /// <returns></returns>
        public async Task ReadFrameData(
            string videoPath,
            int skipFrameCount,
            PartSizeMode_1080P partSize,
            string outputPath,
            int pHashSimilary = Setting.pHashSimilary
        )
        {
            int dataStartIndex = 0;
            // 设置 keyColors
            var keyColors = this.colorGenerator.GeneratedColors.ToDict((color, i) =>
            {
                return (Base64._keyStr[i], color);
            });
            var tempPath = Setting.tempFile;
            try
            {
                Item.logger.Log("重新检测起始颜色序列...");

                // 1. 首先检测起始颜色序列
                int sequenceStartIndex = await this.defaultColorFrameUtils.pureColorFrameDetector.DetectColorSequenceFromIndex(
                    this.defaultColorFrameUtils.StartColors,
                    startIndex: 0,
                    minSequenceLength: Setting.minSequenceLength,  // 允许最少10帧
                    maxSequenceLength: Setting.maxSequenceLength, // 最大为帧重复数量
                    colorTolerance: Setting.colorTolerance   // 颜色容差
                );

                if (sequenceStartIndex == -1)
                {
                    throw new Exception("未找到起始颜色序列");
                }

                Item.logger.Log($"找到起始颜色序列，起始帧索引: {sequenceStartIndex}");

                // 2. 计算数据开始位置 (起始序列结束后的位置 + 跳过帧数量)
                dataStartIndex = sequenceStartIndex +
                    this.defaultColorFrameUtils.StartColors.Count * Setting.frameRepetition +
                    skipFrameCount;
                Item.logger.Log($"色块帧开始位置: {dataStartIndex}");
            }
            catch (Exception ex)
            {
                throw new Exception($"读取色块帧数据失败: {ex.Message}", ex);
            }

            // 3. 从数据开始位置读取Base64编码后的数据
            using(Loading loading = new Loading(this.defaultColorFrameUtils.pureColorFrameDetector.TotalFrames, "开始读取数据..."))
            {
                loading.Show();
                loading.Update(dataStartIndex);

                await Task.Run(() =>
                {
                    ImageDiffUtils diffUtils = new ImageDiffUtils();
                    var buffer = new byte[partSize.FrameSizeNoError()];
                    int similaryIndex = 0;
                    bool readDown = false;
                    using (VideoCapture capture = new VideoCapture(videoPath))
                    using (Mat currentMat = new Mat())
                    using (FileStream tempFile = new FileInfo(tempPath).OpenWrite())
                    using (StreamWriter sw = new StreamWriter(tempFile,Encoding.ASCII))
                    {
                        // 历史帧
                        var lastMat = new Mat();
                        if (!capture.IsOpened()) throw new Exception("无法打开视频文件");
                        for (int frameIndex = dataStartIndex; frameIndex < this.defaultColorFrameUtils.pureColorFrameDetector.TotalFrames; frameIndex++)
                        {
                            capture.Set(VideoCaptureProperties.PosFrames, frameIndex);
                            capture.Read(currentMat);

                            if (!currentMat.Empty())
                            {
                                if (PureColorFrameDetector.IsSolidColorSafe(currentMat))
                                {
                                    continue;
                                }

                                // 色块帧变化了
                                if (diffUtils.PHashSimilarity(lastMat,currentMat) < pHashSimilary)
                                {
                                    lastMat.Dispose();
                                    lastMat = currentMat.Clone();
                                    if (similaryIndex< frameRepetition * 0.8 && similaryIndex > 0) // 至少要重复 80% 的帧量
                                    {
                                        throw new Exception("重复帧数量不够,视频文件可能被破坏了!");
                                    }
                                    else
                                    {
                                        similaryIndex = 0;
                                        readDown = false;
                                    }
                                }
                                else
                                {
                                    similaryIndex++;
                                    if (similaryIndex >= frameRepetition * 0.5 && readDown == false) // 取重复帧中间的作为数据来源
                                    {
                                        string tempData = currentMat.ConvertMat2StringWithAverage(partSize, keyColors);
                                        sw.Write(tempData);
                                        readDown = true;
                                    }
                                }
                                // 更新进度
                                loading.Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    loading.Update(frameIndex, "正在读取帧数据到临时文件中" + ".".Repeat(frameIndex % 4));
                                }), System.Windows.Threading.DispatcherPriority.Background);
                            }
                        }
                    }

#if DEBUG
                    // 打开临时文件
                    Item.OpenFile(tempPath);
#endif

                    // 读取临时文件并写入文件
                    using (FileStream tempStream = File.OpenRead(tempPath))
                    using (FileStream writeStream = File.Create(outputPath))
                    using (StreamWriter sw = new StreamWriter(writeStream))
                    {
                        int index = 0;
                        int fileCount = (int)tempStream.Length;
                        buffer = new byte[Setting.bufferSize>tempStream.Length?Setting.bufferSize:tempStream.Length];
                        while (index < tempStream.Length)
                        {
                            // 每次读取一个缓冲方位内的数据,然后根据参数解码
                            tempStream.Read(buffer, 0, buffer.Length);
                            if (index + buffer.Length > tempStream.Length) buffer = buffer.Take((int)tempStream.Length - index).ToArray();
                            string tempStr = Encoding.ASCII.GetString(buffer);
                            byte[] tempBuffer = Base64.DecodeBytes(tempStr);
                            switch (encryptMode)
                            {
                                case EncryptMode.AES:
                                    tempBuffer = AES.Decrypt(tempBuffer, Key);
                                    break;
                                case EncryptMode.BASE64:
                                    var tStr = Encoding.UTF8.GetString(tempBuffer);
                                    tempBuffer = Base64.DecodeBytes(tStr, Key);
                                    break;
                                default:
                                    break;
                            }
                            writeStream.Write(tempBuffer, 0, tempBuffer.Length);
                            index += buffer.Length;

                            // 更新进度条
                            loading.Dispatcher.Invoke(() =>
                            {
                                loading.Update(index, "正在解析文件" + ".".Repeat(((int)(index / Setting.bufferSize)) % 4));
                            }, System.Windows.Threading.DispatcherPriority.Background);
                        }
                    }
                });
            }
        }

        /// <summary>
        /// 将字符串写入视频
        /// <br />
        /// 多色块帧
        /// <br />
        /// 此方法会调用 loading 窗口
        /// </summary>
        /// <param name="text"></param>
        /// <param name="partSize"></param>
        /// <returns></returns>
        public async Task WriteStringIntoVideo(string text,PartSizeMode_1080P partSize,List<Color> colors = null)
        {
            // loading
            using (Loading loading = new Loading(text.Length,"正在写入数据."))
            {
                loading.Show();

                // 启动后台任务
                await Task.Run(() =>
                {
                    // 获取颜色列表
                    var colorlist = colors ?? this.colorGenerator.GeneratedColors;
                    Dictionary<char, Color> keyColors = colors.ToDict((c, i) =>
                    {
                        return (Base64._keyStr[i], c);
                    });

                    // 确保VideoWriter成功打开
                    if (!_videoWriter.IsOpened())
                    {
                        throw new Exception("无法创建视频文件，请检查编码器支持");
                    }

                    // 创建色块帧并写入视频
                    var strings = text.SplitByPartSize(partSize);
                    for (int i = 0; i < strings.Count; i++)
                    {
                        string str = strings[i];
                        using (Mat mat = ConvertSplitString2Mat(str,partSize,keyColors))
                        {
                            for (int j = 0; j < Setting.frameRepetition; j++)
                            {
                                using (Mat tempMat = mat.Clone())
                                {
                                    _videoWriter.Write(tempMat);
                                }
                            }
                        }

                        // 更新进度, 通过Dispatcher在UI线程上更新
                        loading.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            loading.Update(i, strings.Count, "正在写入数据" + ".".Repeat(i % 4));
                        }), System.Windows.Threading.DispatcherPriority.Background);
                    }
                });
            }
        }

        /// <summary>
        /// 将分割后的字符串转换为当前帧
        /// </summary>
        /// <param name="cutString"></param>
        /// <param name="keyColors"></param>
        /// <returns></returns>
        private Mat ConvertSplitString2Mat(string cutString,PartSizeMode_1080P partSize,Dictionary<char,Color> keyColors = null)
        {
            int maxLenght = partSize.FrameSizeNoError();
            if (maxLenght > cutString.Length) return null;

            // 设置 keyColors
            keyColors = keyColors ?? this.colorGenerator.GeneratedColors.ToDict((color, i) =>
            {
                return (Base64._keyStr[i], color);
            });

            // 开始尝试生成Mat
            var partSizeValue = (int)partSize;
            Mat newMat = new Mat(Setting.height,Setting.width, MatType.CV_8UC3);

            // 开始渲染颜色
            int row = Setting.width / partSizeValue;
            int col = Setting.height / partSizeValue;
            int index = 0;
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    char c = cutString[index++];
                    Color color = Color.Transparent;
                    if (keyColors.Keys.Contains(c))
                    {
                        color = keyColors[c];
                    }
                    // 将AWT Color转换为OpenCV Scalar (注意颜色顺序: BGR)
                    Scalar scalar = new Scalar(color.B, color.G, color.R);

                    // 计算当前色块在Mat中的像素范围
                    int startX = i * partSizeValue;
                    int endX = (i + 1) * partSizeValue;
                    int startY = j * partSizeValue;
                    int endY = (j + 1) * partSizeValue;

                    // 使用当前颜色填充对应区域
                    newMat[new Range(startY, endY), new Range(startX, endX)].SetTo(scalar);
                }
            }

            return newMat;
        }

        /// <summary>
        /// 打开文件并写入视频
        /// <br />
        /// 使用 Loading 界面显示进度条
        /// <br />
        /// 会先创建一个临时文件,读取文件并按照 EncryptMode 决定是否加密
        /// 然后通过 base64 编码将数据写入到临时文件中
        /// <br />
        /// 然后再通过 OpenCV 按照 partSize 将临时文件写入到视频文件中
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task OpenFileWrite2Video(string path,Dictionary<char,Color> keyColors = null)
        {
            // 设置 keyColors
            keyColors = keyColors ?? this.colorGenerator.GeneratedColors.ToDict((color, i) =>
            {
                return (Base64._keyStr[i], color);
            });

            FileInfo file = new FileInfo(path);
            if (file.Exists == false) throw new IOException($"文件: {path}不存在");
            if (partSize == PartSizeMode_1080P.None) throw new Exception("请选择一个合适的帧大小");
            var FileSize = file.Length;
            using (FileStream readStream = file.OpenRead())
            using (Loading loading = new Loading((int)FileSize, "正在创建临时文件..."))
            {
                loading.Show();
                // 开始任务
                await Task.Run(() =>
                {
                    // 创建临时文件
                    string tempPath = Setting.tempFile;
                    if (File.Exists(tempPath)) File.Delete(tempPath);
                    using (FileStream writeStream = File.Create(tempPath))
                    using (StreamWriter streamWriter = new StreamWriter(writeStream,Encoding.ASCII))
                    {
                        // 每次读取3mb的数据,通过 encryptMode 判断是否加密
                        // 然后进行base64编码,最后写入到临时文件中
                        int index = 0;
                        byte[] buffer = new byte[Setting.bufferSize>file.Length? file.Length: Setting.bufferSize];
                        while (index < file.Length)
                        {
                            readStream.Read(buffer, 0, buffer.Length);
                            if (index + buffer.Length > file.Length) buffer = buffer.Take((int)file.Length - index).ToArray();
                            byte[] tempBuffer;
                            switch (encryptMode)
                            {
                                case EncryptMode.AES:
                                    tempBuffer = AES.Encrypt(buffer, Key);
                                    break;
                                case EncryptMode.BASE64:
                                    var tStr = Base64.Encode(buffer, Key);
                                    tempBuffer = Encoding.UTF8.GetBytes(tStr);
                                    break;
                                default:
                                    tempBuffer = buffer;
                                    break;
                            }
                            var tempStr = Base64.Encode(tempBuffer);
                            streamWriter.Write(tempStr);
                            index += buffer.Length;

                            // 更新进度条
                            loading.Dispatcher.Invoke(() =>
                            {
                                loading.Update(index, "正在写入临时文件" + ".".Repeat(((int)(index / Setting.bufferSize)) % 4));
                            }, System.Windows.Threading.DispatcherPriority.Background);
                        }
                    }

#if DEBUG
                    // 打开临时文件
                    Item.OpenFile(tempPath); 
#endif

                    // 读取临时文件并且写入视频
                    using (FileStream tempStream = File.OpenRead(tempPath))
                    {
                        int index = 0;
                        int fileCount = (int)tempStream.Length;
                        byte[] buffer = new byte[partSize.FrameSize()]; // 每次读取一个帧大小的数据
                        while (index < tempStream.Length)
                        {
                            // 每次读取一个帧大小的数据量,转换成Mat,然后重复写入
                            tempStream.Read(buffer, 0, buffer.Length);
                            string miniPart = Encoding.ASCII.GetString(buffer);
                            using (Mat mat = ConvertSplitString2Mat(miniPart,partSize,keyColors))
                            {
                                for (int j = 0; j < frameRepetition; j++)
                                {
                                    using (Mat tempMat = mat.Clone())
                                    {
                                        _videoWriter.Write(tempMat); // 写入帧
                                    }
                                }
                            }
                            // 显示进度
                            index += buffer.Length;
                            // 更新进度, 通过Dispatcher在UI线程上更新
                            loading.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                loading.Update(index, fileCount, "正在写入数据" + ".".Repeat((index/buffer.Length) % 4));
                            }), System.Windows.Threading.DispatcherPriority.Background);
                        }
                    }
                });
            }
        }

        /// <summary>
        /// 销毁资源
        /// </summary>
        public void Dispose()
        {
            // 释放视频写入器资源
            if (_videoWriter != null)
            {
                _videoWriter.Release();
                _videoWriter.Dispose();
                _videoWriter = null;
            }
            // 释放颜色生成器资源
            if (colorGenerator != null)
            {
                //colorGenerator.Dispose();
                colorGenerator = null;
            }
            // 释放默认纯色数据帧工具资源
            if (defaultColorFrameUtils != null)
            {
                defaultColorFrameUtils.Dispose();
                defaultColorFrameUtils = null;
            }
            // 强制垃圾回收
            GC.Collect();
        }
    }
}
